package org.csu.sei.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.JsonObject;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
//import jdk.internal.org.jline.utils.Log;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.csu.sei.common.PageRes;
import org.csu.sei.entity.DTO.Batch;
import org.csu.sei.entity.DTO.PasswordChange;
import org.csu.sei.entity.News;
import org.csu.sei.entity.User;
import org.csu.sei.service.IUserService;
import org.csu.sei.common.ReturnJson;
//import org.json.JSONException;
//import org.json.JSONObject;
import org.csu.sei.util.MD5Util;
import org.csu.sei.util.TokenUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.kafka.KafkaProperties;
import org.springframework.boot.web.servlet.server.Session;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.spring.web.json.Json;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Type;
import java.util.*;

import static org.csu.sei.common.BaseConstant.ErrorCode.*;
import static org.csu.sei.common.BaseConstant.Role.*;

@RestController
@RequestMapping("/user")

public class UserController {

    @Resource
    private IUserService userService;

    private static final Logger logger = LoggerFactory.getLogger(NewsController.class);

    private Set<String> tokenSet = new HashSet<>();

    @PostMapping("/accounts")
    @ApiOperation(value = "注册接口")
    public JSONObject register(@RequestBody User user) {
        JSONObject data = new JSONObject();
        String msg = "";
        int status = 200;
        int code = 0;

        user.setPassword(MD5Util.formPassToDBPass(user.getPassword()));
        User checkuser = userService.selectUserByUsername(user.getUsername());
        if(checkuser != null){
            return ReturnJson.defaultFailureRes(USER_USERNAME_EXIST);
        }else if (user.getPassword()==null||user.getPassword().equals("")){
            return ReturnJson.defaultFailureRes(USER_PASSWORD_NULL);
        }else {
            user.setId(null);//消除id由数据库来分配
            user.setRole(WAITINGPASS.getCode());//设为2等待管理员通过
            userService.insertUser(user);
            user = userService.selectUserByUsername(user.getUsername());
            user.setPassword(null);
        }

        data.put("user",user);
        return ReturnJson.successRes(data);
    }

    @PutMapping("/account")
    @ApiOperation(value = "用户信息修改接口", notes = "1.用户密码不可修改，2.需要验证token")
    public JSONObject updateUserInfo(@RequestBody User user) {
        JSONObject data = new JSONObject();
        String msg = "";
        int code = 0;
        int status = 200;

        user.setPassword(userService.selectUserById(user.getId()).getPassword());//保持密码
        userService.updateUserInfo(user);
//        user = userService.selectUserByUsername(user.getUsername());
        data.put("userupdate",user);
        return ReturnJson.successRes(data);
    }

    @PutMapping("/password")
    @ApiOperation(value = "密码修改接口",notes = "需要验证原密码")
    public JSONObject updateUserPasswd(@RequestHeader (value = "token",required = false)String token,@RequestBody Map<String,Object> userpassmap){
        User checkuser = TokenUtil.getUserData(token);//验证token中的用户名用

        //修改密码
        JSONObject data = new JSONObject();
        String msg = "";
        int code = 0;
        int status = 200;


//        String identifierId = (String) userpassmap.get("userid");
        int identifierId = (Integer) userpassmap.get("userid");
        String passwd = (String) userpassmap.get("passwd");
        String newPasswd = (String) userpassmap.get("new_passwd");
//        Long userid = Long.valueOf(identifierId);
        Integer id = (Integer) userpassmap.get("userid");
        Long userid = id.longValue();
        passwd = MD5Util.formPassToDBPass(passwd);

        if(userid != checkuser.getId() && checkuser.getRole() != 0){
            return ReturnJson.failureResWithMsg(USER_HAVENOT_PERMIT,"权限不足");
        }

        User user = userService.selectUserById(userid);
        if (newPasswd==null || newPasswd.equals("")){
            code = 41002;
            msg = "passwd can not be empty";
            return ReturnJson.defaultFailureRes(USER_PASSWORD_NULL);
        }else if(!passwd.equals(user.getPassword())){
            code = 43001;
            msg = "erro passwd";
            return ReturnJson.defaultFailureRes(USER_PASSWORD_ERROR);
        }else {
            user.setPassword(MD5Util.formPassToDBPass(newPasswd));
            userService.updateUserInfo(user);//用updateUserInfo函数更新用户信息中的密码
            msg = "ok";
        }
        return ReturnJson.ackWithMsg("修改成功");
    }

    @PostMapping("/password")
    @ApiOperation(value = "忘记密码接口",notes = "目前的方案是回答问题，后续可能增加邮箱方案")
    public JSONObject fogotUserPasswd(@RequestBody Map<String,Object> qaMapper){
        //忘记密码
        JSONObject data = new JSONObject();
        String msg = "";
        int code = 0;
        boolean res = true;
        int status = 200;

//        String username = (String) qaMapper.get("userid");
//
//        Long userid = Long.valueOf(0);
//
//        if(userService.selectUserByUsername(username) == null){
//            try {
//                userid = Long.valueOf(username);
//                if(userService.selectUserById(userid) == null){//无对应id的用户
//                    code = 44001;
//                    msg = "user not exits";
//                }
//            }
//            catch (Exception ex){//字符转换错误说明用户id不合法，无对应用户
//                code = 44001;
//                msg = "user not exits";
//            }
//        }else {
//            userid = userService.selectUserByUsername(username).getId();
//        }
        Long userid = Long.valueOf((int) qaMapper.get("userid"));

        String answer = (String) qaMapper.get("answer");


        if(answer.equals(userService.selectAnswerFromUserId(userid))){
            String passwd = userService.selectUserById(userid).getPassword();
            data.put("user",userid);
            data.put("res" , res);
            data.put("passwd",passwd);
            return ReturnJson.successRes(data);
        }
        else{
            return ReturnJson.defaultFailureRes(USER_ANSWER_ERROR);
        }
    }

    @PostMapping("/token")
    @ApiOperation(value = "登录接口" , notes = "返回token请客户端保存")
    public JSONObject login(@RequestBody Map<String,Object> user_info){
        JSONObject data = new JSONObject();

        String username = (String) user_info.get("identifierId");
        String passwd = (String) user_info.get("password");

        System.out.println(passwd);

        passwd = MD5Util.formPassToDBPass(passwd);

        System.out.println(passwd);

        User user = userService.selectUserByUsername(username);
        if(user == null){
            try {
                Long userid = Long.parseLong(username);
                user = userService.getById(userid);
            }catch (Exception e){
                System.out.println(e);
            }

        }
        if(user == null){
            return ReturnJson.defaultFailureRes(USER_NOT_EXIST);
        }

        if(user.getPassword().equals(passwd)){
            String token = TokenUtil.getUserToken(user);
            User user1 = TokenUtil.getUserData(token);
//            System.out.println("user:"+user1.getId()+user1.getRole());
            logger.info("user: "+user1.getId()+" is"+user1.getRole()+" login");

            if (user.getRole() > 2){
                return ReturnJson.failureResWithMsg(USER_HAVENOT_PERMIT,"您的注册请求尚未通过");
            }
            data.put("token" , token);
            data.put("role",user.getRole());
        }else {
            return ReturnJson.defaultFailureRes(USER_PASSWD_WRONG);
        }


        return ReturnJson.successRes(data);
    }

    @GetMapping("/wait")
    @ApiOperation(value = "获取要注册的用户",notes = "批准用户注册时应用")
    public JSONObject GetWaitRegister(){
        JSONObject data = new JSONObject();
        String msg = "";
        //测试部分
        User user = new User();
        List<User> userList = userService.selectUserUnReg();

        data.put("userlist",userList);
        return ReturnJson.successRes(data);
    }

    @PostMapping("/permission")
    @ApiOperation(value = "通过注册请求接口",notes = "注册需要后台许可，管理员登录后台允许注册编辑者的申请，" +
            "首个root管理员要直接加入数据库而非通过注册")
    public JSONObject permitTheWaitingUser(@RequestBody Map<String,Object> permition){
        Long userid = Long.valueOf(0);
        int status = 200;
        int code = 0;
        JSONObject data = new JSONObject();
        String msg = "";

        userid = Long.valueOf((int) permition.get("userid"));
        int permit = userService.updateUserRole(userid, REGULATOR.getCode());
        if (permit == 0){
            code = 44001;
            msg = "user not exits";
            return ReturnJson.defaultFailureRes(USER_NOT_EXIST);
        }
        else {
            data.put("permition",true);
        }
        return ReturnJson.successRes(data);
    }

    @GetMapping("/userid")
    @ApiOperation(value = "获取用户id接口",notes = "使前端可以在知道用户名的情况下获取用户id")
    public JSONObject getUserID(@Param("username") String username){
        JSONObject data = new JSONObject();
        String msg = "";
        int status = 200;
        int code = 0;

        Long userid = userService.selectUserByUsername(username).getId();
        if(userid == null){
            code = 44001;
            msg = "user not exits";
            return ReturnJson.defaultFailureRes(USER_NOT_EXIST);
        }else {
            data.put("userid",userid);
        }

        return ReturnJson.successRes(data);
    }

    @GetMapping("/username")
    @ApiOperation(value = "用户名接口",notes = "使用用户id获取其用户名")
    public JSONObject getUserId(@Param("userid") Long userid){
        JSONObject data = new JSONObject();
        String msg = "";
        int status = 200;
        int code = 0;

        String username = userService.selectUserById(userid).getUsername();

        if(username == null){
            code = 44001;
            msg = "user not exits";
            return ReturnJson.defaultFailureRes(USER_NOT_EXIST);
        }else {
            data.put("userid",userid);
        }

        return ReturnJson.successRes(data);
    }

    @GetMapping("/all")
    @ApiOperation(value = "获取所有用户的接口")
    public JSONObject queryAllUser(){
        JSONObject data = new JSONObject();
        List<User> userList = userService.selectAllUser();
        data.put("userList",userList);
        return ReturnJson.successRes(data);
    }

    @GetMapping("/{id}")
    @ApiOperation(value = "根据id获取用户信息接口")
    public JSONObject getUserInfo(@PathVariable Long id){
        JSONObject data = new JSONObject();
        User user = userService.selectUserById(id);

        if (user == null){
            return ReturnJson.defaultFailureRes(USER_NOT_EXIST);
        }

        user.setPassword(null);
        data.put("user",user);
        return ReturnJson.successRes(data);
    }

    @DeleteMapping("/{id}")
    @ApiOperation(value = "根据id删除用户接口")
    public JSONObject deletUserInfo(@PathVariable Long id){
        JSONObject data = new JSONObject();
        int result = userService.deletUserById(id);
        if (result!=0){
            data.put("deletcount",result);
            return ReturnJson.successRes(data);
        }else {
            return ReturnJson.defaultFailureRes(USER_NOT_EXIST);
        }
    }

    @PostMapping("/add_user")
    @ApiOperation(value = "后台增加用户接口")
    public JSONObject addUserByBack(@RequestBody User user){
        JSONObject data = new JSONObject();
        try{
            user.setPassword(MD5Util.formPassToDBPass(user.getPassword()));
            user = userService.insertUser(user);
        }catch (Exception e){
            return ReturnJson.failureResWithMsg(USER_INSERT_ERROR,"insert erro");
        }
        data.put("user",user);
        return ReturnJson.successRes(data);
    }

    @PostMapping("/batch")
    public JSONObject addSome(@RequestBody Batch batch){
        JSONObject data = new JSONObject();
        int role = batch.getRole();
        List<String> usernames = batch.getUsernames();
        System.out.println(usernames.get(0)+"???");
//        List<String> usernames = JSONObject.parseObject(map.get("usernames").toJSONString(), (Type) String.class);
//        int role = JSONObject.parseObject(map.get("role").toJSONString(), (Type) Integer.class);
        if(role < 1 || role > 2){
            ReturnJson.failureResWithMsg(USER_ROLES_FORBIDDEN,"role should be 1 or 2");
        }
        List<User> resList = userService.addSome(usernames,role);
        data.put("ack_list",resList);
        return ReturnJson.successRes(data);
    }

    @DeleteMapping("/delete_some")
    public JSONObject deletSome(@RequestBody List<Long> idList){
        JSONObject data = new JSONObject();
        int count = 0;
        boolean stat = true;

        try{
            count = userService.deleteSome(idList);
        }catch (Exception e){
            stat = false;
        }
        data.put("count",count);
        data.put("stat",stat);
        return ReturnJson.successRes(data);
    }

    @PutMapping("/set_some_edit")
    public JSONObject setSomeEditer(@RequestBody List<Long> idList){
        userService.setSomeRole(idList,REGULATOR.getCode());
        return ReturnJson.ackWithMsg("ok");
    }
    @PutMapping("/set_some_admin")
    public JSONObject setSomeAdmin(@RequestBody List<Long> idList){
        userService.setSomeRole(idList, ADMINISTRATOR.getCode());
        return ReturnJson.ackWithMsg("ok");
    }
    @PutMapping("/set_some_teacher")
    public JSONObject setSomeTeacher(@RequestBody List<Long> idList){
        userService.setSomeRole(idList, TEACHER.getCode());
        return ReturnJson.ackWithMsg("ok");
    }
    @PutMapping("/stop_some")
    public JSONObject stopSome(@RequestBody List<Long> idList){
        userService.setSomeRole(idList, WAITINGPASS.getCode());
        return ReturnJson.ackWithMsg("ok");
    }

    @GetMapping("/condition")
    public JSONObject multipleConditionQuery(
            @RequestParam(value = "page",required = false,defaultValue = "0") int page,
            @RequestParam(value = "limit",required = false,defaultValue = "12")int limit,
            @RequestParam(value = "username",required = false)String name,
            @RequestParam(value = "roles",required = false)List<Integer> roles
    ){
        PageRes userList = userService.queryUserListBySomeCondition(page, limit, name,roles);
        JSONObject json = new JSONObject();
        json.put("page_res",userList);
        return ReturnJson.successRes(json);
    }

    @GetMapping("/info")
    public  JSONObject getUserFromToken(@RequestParam("token") String token){
        JSONObject data = new JSONObject();
        try {
            User user = TokenUtil.getUserData(token);
            user = userService.selectUserById(user.getId());
            JSONObject userJson = (JSONObject) JSONObject.toJSON(user);
            return ReturnJson.successRes(userJson);
        }catch (Exception e){
            return ReturnJson.failureResWithMsg(USER_NOT_EXIST,"token illegal");
        }
    }

    @PutMapping("/accountOnAdmin")
    @ApiOperation(value = "管理员后台修改用户接口")
    public JSONObject changeAccountWithAdminPermit(@RequestBody User user){
        JSONObject data = new JSONObject();
        if(user.getUsername() == null || user.getPassword() == null || user.getUsername().isEmpty() || user.getUsername().isEmpty()){
            user.setPassword(MD5Util.formPassToDBPass(userService.selectUserById(user.getId()).getPassword()));
//            return ReturnJson.failureResWithMsg(USER_PASSWORD_NULL,"用户名密码不能为空");
        }else if(user.getPassword().length()<6){
            return ReturnJson.failureResWithMsg(USER_PASSWORD_ERROR,"密码长度不能小于6位");
        }
        try {
            User checkuser = userService.selectUserById(user.getId());
            if (checkuser == null){
                return ReturnJson.defaultFailureRes(USER_NOT_EXIST);
            }
        }catch (Exception e){
            return ReturnJson.failureResWithMsg(USER_NOT_EXIST,"非法用户");
        }
        user.setPassword(MD5Util.formPassToDBPass(user.getPassword()));
        userService.updateUserInfo(user);
        user.setPassword(null);
        data.put("userupdate",user);
        return ReturnJson.successRes(data);
    }

    //找回密码
    @GetMapping("/{id}/question")
    @ApiOperation(value = "找回密码获取问题")
    public JSONObject getProblem(@PathVariable Long id){
        JSONObject data = new JSONObject();
        String question = "";
        try {
            question=userService.selectQuestion(id);
            data.put("question", question);
            return ReturnJson.successRes(data);
        }catch (Exception e){
            logger.error(e.getMessage());
            return ReturnJson.failureResWithMsg(USER_NOT_EXIST,"账号不存在，请仔细检查");
        }

    }

    //根据回答获取token
    @GetMapping("/reset_token")
    @ApiOperation(value = "改密码的token")
    public JSONObject getTokenFromanswer(@RequestParam("id")String userid , @RequestParam("answer") String answer){
        //忘记密码
        JSONObject data = new JSONObject();
        String msg = "";
        int code = 0;
        boolean res = true;
        int status = 200;
        long id = Long.parseLong(userid);

//        String username = (String) qaMapper.get("userid");
//
//        Long userid = Long.valueOf(0);
//
//        if(userService.selectUserByUsername(username) == null){
//            try {
//                userid = Long.valueOf(username);
//                if(userService.selectUserById(userid) == null){//无对应id的用户
//                    code = 44001;
//                    msg = "user not exits";
//                }
//            }
//            catch (Exception ex){//字符转换错误说明用户id不合法，无对应用户
//                code = 44001;
//                msg = "user not exits";
//            }
//        }else {
//            userid = userService.selectUserByUsername(username).getId();
//        }

//        String answer = (String) qaMapper.get("answer");


        if(answer.equals(userService.selectAnswerFromUserId(id))){
            User user = null;
            try {
                user = userService.getById(id);
            }catch (Exception e){
                logger.error(e.getMessage());
            }
            if (user == null){
                return ReturnJson.failureResWithMsg(USER_NOT_EXIST,"回答用户错误");
            }
            String token = TokenUtil.getPasswordChangeToken(user);
            tokenSet.add(token);
            data.put("token",token);
            Timer t = new Timer();
            t.schedule(new DeleteToken(token),10*60*1000);
            return ReturnJson.successRes(data);
        }
        else{
            return ReturnJson.defaultFailureRes(USER_ANSWER_ERROR);
        }
    }

    @PatchMapping("/password_reset")
    public JSONObject findAndChangePassword(@RequestBody PasswordChange passwordChange){
        boolean flag = false;
        JSONObject data = new JSONObject();
        try {
            flag = TokenUtil.verify(passwordChange.getToken());
            if (!tokenSet.contains(passwordChange.getToken())){
                flag = false;
            }
            if (flag){
                tokenSet.remove(passwordChange.getToken());
                User user = TokenUtil.getUserData(passwordChange.getToken());
                user = userService.selectUserById(user.getId());
                user.setPassword(MD5Util.formPassToDBPass(passwordChange.getNew_passwd()));
                userService.updateById(user);
                user.setPassword(null);
                data.put("user",user);
                return ReturnJson.successRes(data);
            }else {
                return ReturnJson.failureResWithMsg(USER_PASSWORD_ERROR,"用户重置失败");
            }
        }catch (Exception e){
            logger.error("reset_pass_wrong");
            return ReturnJson.failureResWithMsg(USER_PASSWORD_ERROR,"用户重置失败");
        }

    }

    class DeleteToken extends TimerTask{
        String token = null;
        public DeleteToken(String token){
            this.token = token;
        }
        @Override
        public void run(){
            tokenSet.remove(token);
            System.out.println("testok");
        }
    }
}
